/*
 * Copyright (C) 2013 Andreas Stuetz <andreas.stuetz@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.karim;

import java.util.Locale;

import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.database.DataSetSubscriber;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.utils.Pair;

public class MaterialTabs extends ScrollView implements ComponentContainer.ArrangeListener, Component.DrawTask {
    public static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MY_TAG");


    public interface CustomTabProvider {
        Component getCustomTabView(ComponentContainer parent, int position);

        void onCustomTabViewSelected(Component view, int position, boolean alreadySelected);

        void onCustomTabViewUnselected(Component view, int position, boolean alreadyUnselected);
    }

    public interface OnTabReselectedListener {
        void onTabReselected(int position);
    }

    public interface OnTabSelectedListener {
        void onTabSelected(int position);
    }

    // These indexes must be related to the ATTR array above.
    private static final int TEXT_COLOR_PRIMARY = 0;
    private static final int TEXT_SIZE_INDEX = 1;
    private static final int TEXT_COLOR_INDEX = 2;
    private static final int PADDING_INDEX = 3;
    private static final int PADDING_LEFT_INDEX = 4;
    private static final int PADDING_RIGHT_INDEX = 5;

    private final PagerAdapterObserver adapterObserver = new PagerAdapterObserver();

    private final DirectionalLayout.LayoutConfig defaultTabLayoutParams;
    private final DirectionalLayout.LayoutConfig expandedTabLayoutParams;

    private final PageListener pageListener = new PageListener();
    private OnTabSelectedListener tabSelectedListener = null;
    private OnTabReselectedListener tabReselectedListener = null;
    private PageSlider.PageChangedListener delegatePageListener;

    private final DirectionalLayout tabsContainer;
    private PageSlider pager;

    private int tabCount;

    private int mSelectedTabPosition = -1;
    private int currentPosition = 0;
    private float currentPositionOffset = 0f;

    private final Paint rectPaint;

    private int indicatorColor;
    private int indicatorHeight = 2;

    private int underlineHeight = 0;
    private int underlineColor;

    private int tabPadding = 12;
    private int tabTextSize = 14;

    private int tabTextColorUnselected;
    private int tabTextColorSelected;

    private int paddingLeft = 0;
    private int paddingRight = 0;

    private boolean sameWeightTabs = false;
    private boolean textAllCaps = true;
    private boolean isPaddingMiddle = false;

    private Font tabTypefaceUnselected = null;
    private Font tabTypefaceSelected = null;

    private int scrollOffset;
    private int touchScrollOffset;
    private int lastScrollX = 0;

    // Fields from MaterialRippleLayout
    private int rippleColor;
    private int rippleHighlightColor;
    private boolean rippleOverlay;
    private float rippleDiameterDp;
    private int rippleDuration;
    private float rippleAlphaFloat;
    private boolean rippleDelayClick;
    private int rippleFadeDuration;
    private boolean ripplePersistent;
    private boolean rippleInAdapter;
    private float rippleRoundedCornersDp;
    //~ Fields from MaterialRippleLayout

    private Locale locale;

    public MaterialTabs(Context context) {
        this(context, null);
    }

    public MaterialTabs(Context context, AttrSet attrs) {
        this(context, attrs, null);
    }

    public MaterialTabs(Context context, AttrSet attrs, String defStyle) {
        super(context, attrs, defStyle);
//        setMatchViewportEnabled(true);
        tabsContainer = new DirectionalLayout(context);
        tabsContainer.setOrientation(DirectionalLayout.HORIZONTAL);
        tabsContainer.setLayoutConfig(new DirectionalLayout.LayoutConfig(DirectionalLayout.LayoutConfig.MATCH_CONTENT, DirectionalLayout.LayoutConfig.MATCH_PARENT));
        addComponent(tabsContainer);

        indicatorHeight = AttrHelper.vp2px(indicatorHeight, context);
        underlineHeight = AttrHelper.vp2px(underlineHeight, context);
        tabPadding = AttrHelper.vp2px(tabPadding, context);
        tabTextSize = AttrHelper.fp2px(tabTextSize, context);

        tabTextSize = AttrUtils.getDimensionFromAttr(attrs, "textSize", tabTextSize);
        int textPrimaryColor = AttrUtils.getColorFromAttr(attrs, "textColorPrimary", Color.WHITE.getValue());
        tabTextColorUnselected = AttrUtils.getColorFromAttr(attrs, "textColor", textPrimaryColor);

        underlineColor = textPrimaryColor;
        indicatorColor = textPrimaryColor;
        int padding = AttrUtils.getDimensionFromAttr(attrs, "padding", 0);
        paddingLeft = padding > 0 ? padding : AttrUtils.getDimensionFromAttr(attrs, "left_padding", 0);
        paddingRight = padding > 0 ? padding : AttrUtils.getDimensionFromAttr(attrs, "right_padding", 0);

        // Get custom attrs of MaterialTabs.
        indicatorColor = AttrUtils.getColorFromAttr(attrs, "mtIndicatorColor", indicatorColor);
        underlineColor = AttrUtils.getColorFromAttr(attrs, "mtUnderlineColor", underlineColor);
        indicatorHeight = AttrUtils.getDimensionFromAttr(attrs, "mtIndicatorHeight", indicatorHeight);
        underlineHeight = AttrUtils.getDimensionFromAttr(attrs, "mtUnderlineHeight", underlineHeight);
        tabPadding = AttrUtils.getDimensionFromAttr(attrs, "mtTabPaddingLeftRight", tabPadding);
        sameWeightTabs = AttrUtils.getBooleanFromAttr(attrs, "mtSameWeightTabs", sameWeightTabs);
        textAllCaps = AttrUtils.getBooleanFromAttr(attrs, "mtTextAllCaps", textAllCaps);
        isPaddingMiddle = AttrUtils.getBooleanFromAttr(attrs, "mtPaddingMiddle", isPaddingMiddle);
        tabTextColorSelected = AttrUtils.getColorFromAttr(attrs, "mtTextColorSelected", textPrimaryColor);

        // Get custom attrs of MaterialRippleLayout.
        rippleColor = AttrUtils.getColorFromAttr(attrs, "mtMrlRippleColor", MaterialRippleLayout.DEFAULT_COLOR);
        // Making default ripple highlight color the same as rippleColor but with 1/4 the alpha.
        RgbColor rgbColor = RgbColor.fromArgbInt(rippleColor);
        rippleHighlightColor = Color.argb((int) (rgbColor.getAlpha() * 0.25), rgbColor.getRed(), rgbColor.getGreen(),
                rgbColor.getBlue());
        rippleHighlightColor = AttrUtils.getColorFromAttr(attrs, "mtMrlRippleHighlightColor", rippleHighlightColor);
        rippleDiameterDp = AttrUtils.getDimensionFromAttr(attrs, "mtMrlRippleDiameter", MaterialRippleLayout.DEFAULT_DIAMETER_DP);
        rippleOverlay = AttrUtils.getBooleanFromAttr(attrs, "mtMrlRippleOverlay", MaterialRippleLayout.DEFAULT_RIPPLE_OVERLAY);
        rippleDuration = AttrUtils.getIntegerFromAttr(attrs, "mtMrlRippleDuration", MaterialRippleLayout.DEFAULT_DURATION);
        rippleAlphaFloat = AttrUtils.getFloatFromAttr(attrs, "mtMrlRippleAlpha", MaterialRippleLayout.DEFAULT_ALPHA);
        rippleDelayClick = AttrUtils.getBooleanFromAttr(attrs, "mtMrlRippleDelayClick", MaterialRippleLayout.DEFAULT_DELAY_CLICK);
        rippleFadeDuration = AttrUtils.getIntegerFromAttr(attrs, "mtMrlRippleFadeDuration", MaterialRippleLayout.DEFAULT_FADE_DURATION);
        ripplePersistent = AttrUtils.getBooleanFromAttr(attrs, "mtMrlRipplePersistent", MaterialRippleLayout.DEFAULT_PERSISTENT);
        rippleInAdapter = AttrUtils.getBooleanFromAttr(attrs, "mtMrlRippleInAdapter", MaterialRippleLayout.DEFAULT_SEARCH_ADAPTER);
        rippleRoundedCornersDp = AttrUtils.getDimensionFromAttr(attrs, "mtMrlRippleRoundedCorners", MaterialRippleLayout.DEFAULT_ROUNDED_CORNERS_DP);

        setMarginBottomTabContainer();

        rectPaint = new Paint();
        rectPaint.setAntiAlias(true);
        rectPaint.setStyle(Paint.Style.FILL_STYLE);

        defaultTabLayoutParams = new DirectionalLayout.LayoutConfig(DirectionalLayout.LayoutConfig.MATCH_PARENT, DirectionalLayout.LayoutConfig.MATCH_PARENT);
        expandedTabLayoutParams = new DirectionalLayout.LayoutConfig(DirectionalLayout.LayoutConfig.MATCH_CONTENT, DirectionalLayout.LayoutConfig.MATCH_PARENT, LayoutAlignment.CENTER, 1);

        if (locale == null) {
            locale = Locale.ROOT;
        }
        setArrangeListener(this);
        addDrawTask(this);
        addScrolledListener((component, scrollX, scrollY, oldScrollX, oldScrollY) -> {
            touchScrollOffset += (oldScrollX - scrollX);
            invalidate();
        });
    }

    private void setMarginBottomTabContainer() {
        StackLayout.LayoutConfig mlp = (StackLayout.LayoutConfig) tabsContainer.getLayoutConfig();
        int bottomMargin = Math.max(indicatorHeight, underlineHeight);
        mlp.setMargins(mlp.getMarginLeft(), mlp.getMarginTop(), mlp.getMarginRight(), bottomMargin);
        tabsContainer.setLayoutConfig(mlp);
    }

    /**
     * 设置pageSlider
     *
     * @param pager pager
     * @throws IllegalStateException IllegalStateException
     */
    public void setViewPager(PageSlider pager) {
        this.pager = pager;
        if (pager.getProvider() == null) {
            throw new IllegalStateException("ViewPager does not have adapter instance.");
        }

        pager.addPageChangedListener(pageListener);
        pager.getProvider().addDataSubscriber(adapterObserver);
        adapterObserver.setAttached(true);
        notifyDataSetChanged();
    }

    /**
     * 刷新数据
     */
    public void notifyDataSetChanged() {
        tabsContainer.removeAllComponents();
        tabCount = pager.getProvider().getCount();
        Component tabView;
        for (int i = 0; i < tabCount; i++) {
            if (pager.getProvider() instanceof CustomTabProvider) {
                tabView = ((CustomTabProvider) pager.getProvider()).getCustomTabView(this, i);
            } else {
                tabView = LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_mt_tab, null, false);
            }

            MaterialRippleLayout materialRippleLayout = MaterialRippleLayout.on(tabView)
                    .rippleAlpha(rippleAlphaFloat)
                    .rippleColor(rippleColor)
                    .rippleDelayClick(rippleDelayClick)
                    .rippleDiameterDp(rippleDiameterDp)
                    .rippleDuration(rippleDuration)
                    .rippleFadeDuration(rippleFadeDuration)
                    .rippleHighlightColor(rippleHighlightColor)
                    .rippleInAdapter(rippleInAdapter)
                    .rippleOverlay(rippleOverlay)
                    .ripplePersistent(ripplePersistent)
                    .rippleRoundedCornersDp(rippleRoundedCornersDp)
                    .create();
            CharSequence title = pager.getProvider().getPageTitle(i);
            addTab(i, title, materialRippleLayout);
        }

        updateTabStyles();
        setLayoutRefreshedListener(new LayoutRefreshedListener() {
            @Override
            public void onRefreshed(Component component) {
            }
        });
    }

    private void addTab(final int position, CharSequence title, Component tabView) {
        Text textView = (Text) tabView.findComponentById(ResourceTable.Id_mt_tab_title);
        if (textView != null) {
            if (title != null) {
                textView.setText(title.toString());
            }
        }
        tabView.setFocusable(FOCUS_ENABLE);
        tabView.setClickedListener(new ClickedListener() {
            @Override
            public void onClick(Component v) {
                if (tabSelectedListener != null) {
                    tabSelectedListener.onTabSelected(position);
                }

                if (pager.getCurrentPage() != position) {
                    markNotSelected(position);
                    pager.setCurrentPage(position);
                } else if (tabReselectedListener != null) {
                    tabReselectedListener.onTabReselected(position);
                }
            }
        });
        tabsContainer.addComponent(tabView, position, sameWeightTabs ? expandedTabLayoutParams : defaultTabLayoutParams);
    }

    private void updateTabStyles() {
        for (int i = 0; i < tabCount; i++) {
            Component v = tabsContainer.getComponentAt(i);
            v.setPadding(tabPadding, v.getPaddingTop(), tabPadding, v.getPaddingBottom());
            Text tab_title = (Text) v.findComponentById(ResourceTable.Id_mt_tab_title);

            if (tab_title != null) {
                tab_title.setTextSize(tabTextSize, Text.TextSizeType.PX);
                tab_title.setTextColor(new Color(tabTextColorUnselected));
                if (tabTypefaceUnselected != null) {
                    tab_title.setFont(tabTypefaceUnselected);
                }
                // setAllCaps() is only available from API 14, so the upper case is made manually if we are on a pre-ICS-build.
                if (textAllCaps) {
                    tab_title.setText(tab_title.getText().toUpperCase(locale));
                }
            }
        }
    }

    private void scrollToChild(int position, int offset) {
        if (tabCount == 0) {
            return;
        }

        int newScrollX = tabsContainer.getComponentAt(position).getLeft() + offset;
        if (position > 0 || offset > 0) {
            // Half screen offset. Either tabs start at the middle of the view scrolling straight away or tabs start at the beginning (no padding)
            // scrolling when indicator gets to the middle of the view width.
            newScrollX -= scrollOffset;
            Pair<Float, Float> lines = getIndicatorCoordinates();
            newScrollX += ((lines.s - lines.f) / 2);
        }

        if (newScrollX != lastScrollX) {
            lastScrollX = newScrollX;
            fluentScrollTo(newScrollX, 0);
        }
    }

    private Pair<Float, Float> getIndicatorCoordinates() {
        // Default: line is below current tab.
        Component currentTab = tabsContainer.getComponentAt(selectedPosition);
        // 滑动后你重新绘制的位置必须要加上你滑动的距离不然 就会绘制到其他位置！！
        float lineLeft = currentTab.getLeft() + touchScrollOffset;
        float lineRight = currentTab.getRight() + touchScrollOffset;
        // If there is an offset, start interpolating left and right coordinates between current and next tab.
        if (currentPosition < tabCount - 1 && !isClick) {

            Component nextTab = tabsContainer.getComponentAt(currentPositionOffset > 0 ? currentPosition + 1 : currentPosition);
            final float nextTabLeft = nextTab.getLeft() + touchScrollOffset;
            final float nextTabRight = nextTab.getRight() + touchScrollOffset;

            lineLeft = (Math.abs(currentPositionOffset) * nextTabLeft + (1f - Math.abs(currentPositionOffset)) * lineLeft);
            lineRight = (Math.abs(currentPositionOffset) * nextTabRight + (1f - Math.abs(currentPositionOffset)) * lineRight);
        }
        return new Pair<>(lineLeft, lineRight);
    }

    private boolean isRefreshed;

    @Override
    public boolean onArrange(int i, int i1, int i2, int i3) {
        if (isPaddingMiddle || paddingLeft > 0 || paddingRight > 0) {
            // Make sure tabContainer is bigger than the HorizontalScrollView to be able to scroll.
            tabsContainer.setMinWidth(getWidth());
            // Clipping padding to false to see the tabs while we pass them swiping.
            setClipEnabled(false);
        }

        if (tabsContainer.getChildCount() > 0) {
            tabsContainer.getComponentAt(0).setLayoutRefreshedListener(new LayoutRefreshedListener() {
                @Override
                public void onRefreshed(Component component) {
                    if (isRefreshed) {
                        return;
                    }
                    Component view = tabsContainer.getComponentAt(0);

                    if (isPaddingMiddle) {
                        int mHalfWidthFirstTab = view.getWidth() / 2;
                        paddingLeft = paddingRight = getWidth() / 2 - mHalfWidthFirstTab;
                    }
                    tabsContainer.setPadding(paddingLeft, getPaddingTop(), paddingRight, getPaddingBottom());
                    if (scrollOffset == 0) {
                        scrollOffset = getWidth() / 2 - paddingLeft;
                    }
                    currentPosition = pager.getCurrentPage();
                    currentPositionOffset = 0f;
                    scrollToChild(currentPosition, 0);
                    selectTab(currentPosition);
                    invalidate();
                    isRefreshed = true;
                }
            });
        }
        return false;
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (tabCount == 0) {
            return;
        }
        if (sameWeightTabs && tabsContainer.getWidth() <= getWidth()) {
            tabsContainer.setLayoutConfig(new DirectionalLayout.LayoutConfig(
                    DirectionalLayout.LayoutConfig.MATCH_PARENT, DirectionalLayout.LayoutConfig.MATCH_PARENT));
        }
        HiLog.debug(label, "onDraw=" + getLeft() + "   mtab=" + tabsContainer.getLeft());
        final int height = getHeight();
        // Draw indicator line.
        rectPaint.setColor(new Color(indicatorColor));
        Pair<Float, Float> lines = getIndicatorCoordinates();
        canvas.drawRect(lines.f + paddingLeft, height - indicatorHeight, lines.s + paddingLeft, height, rectPaint);
        // Draw underline.
        rectPaint.setColor(new Color(underlineColor));
        canvas.drawRect(paddingLeft, height - underlineHeight, tabsContainer.getWidth() + paddingRight, height, rectPaint);
    }

    /**
     * 设置重复选择监听
     *
     * @param tabReselectedListener listener
     */
    public void setOnTabReselectedListener(OnTabReselectedListener tabReselectedListener) {
        this.tabReselectedListener = tabReselectedListener;
    }

    /**
     * 设置选择监听
     *
     * @param tabSelectedListener listener
     */
    public void setOnTabSelectedListener(OnTabSelectedListener tabSelectedListener) {
        this.tabSelectedListener = tabSelectedListener;
    }

    /**
     * 设置page改变监听
     *
     * @param listener listener
     */
    public void setOnPageChangeListener(PageSlider.PageChangedListener listener) {
        this.delegatePageListener = listener;
    }

    private int mState;
    private int selectedPosition;
    private boolean isClick;

    private class PageListener implements PageSlider.PageChangedListener {

        @Override
        public void onPageSliding(int position, float positionOffset, int positionOffsetPixels) {
            if (mState == 0) {
                return;
            }
            currentPosition = positionOffsetPixels < 0 ? position - 1 : position;
            currentPositionOffset = positionOffsetPixels < 0 ? -positionOffset : positionOffset;
            if (currentPosition + 1 == tabsContainer.getChildCount() - 1) {
                currentPositionOffset = (float) positionOffsetPixels / (float) tabsContainer.getWidth();
            }
            if (mState == 2 && selectedPosition != position) {
                currentPosition = selectedPosition;
            }
            isClick = selectedPosition != position;
            int offset = tabCount > 0 ? (int) (currentPositionOffset * tabsContainer.getComponentAt(currentPosition).getWidth()) : 0;
            HiLog.error(label, "onPageSliding position=" + currentPosition
                    + "   positionOffset=" + currentPositionOffset + "   positionOffsetPixels=" + positionOffsetPixels + "  offset=" + offset);
            scrollToChild(currentPosition, offset);
            invalidate();
            if (delegatePageListener != null) {
                delegatePageListener.onPageSliding(position, positionOffset, positionOffsetPixels);
            }
        }

        @Override
        public void onPageSlideStateChanged(int state) {
            mState = state;
            HiLog.debug(label, "onPageSliding  state=" + state);
            if (delegatePageListener != null) {
                delegatePageListener.onPageSlideStateChanged(state);
            }
        }

        @Override
        public void onPageChosen(int position) {
            updateSelection(position);
            selectedPosition = position;
            HiLog.debug(label, "onPageSliding=" + position);
            if (delegatePageListener != null) {
                delegatePageListener.onPageChosen(position);
            }
        }
    }

    private void selectTab(int currentItem) {
        markSelected(currentItem);
        for (int i = 0; i < tabCount; i++) {
            if (i != currentItem) {
                markNotSelected(i);
            }
        }
        mSelectedTabPosition = currentItem;
    }

    private void updateSelection(int position) {
        selectTab(position);
    }

    private void markNotSelected(int position) {
        Component tab = tabsContainer.getComponentAt(position);
        if (tab != null) {
            Text title = (Text) tab.findComponentById(ResourceTable.Id_mt_tab_title);
            if (title != null) {
                if (tabTypefaceUnselected != null) {
                    title.setFont(tabTypefaceUnselected);
                } else {
                    title.setFont(Font.DEFAULT);
                }
                title.setTextColor(new Color(tabTextColorUnselected));
            } else if (pager.getProvider() instanceof CustomTabProvider) {
                if (tab instanceof MaterialRippleLayout) {
                    final Component child = ((MaterialRippleLayout) tab).getComponentAt(0);
                    ((CustomTabProvider) pager.getProvider()).onCustomTabViewUnselected(child, position, !isTabSelected(position));
                } else {
                    ((CustomTabProvider) pager.getProvider()).onCustomTabViewUnselected(tab, position, !isTabSelected(position));
                }
            }
        }
    }

    private void markSelected(int position) {
        Component tab = tabsContainer.getComponentAt(position);
        if (tab != null) {
            Text title = (Text) tab.findComponentById(ResourceTable.Id_mt_tab_title);
            if (title != null) {
                if (tabTypefaceSelected != null) {
                    title.setFont(tabTypefaceSelected);
                } else {
                    title.setFont(Font.DEFAULT_BOLD);
                }
                title.setTextColor(new Color(tabTextColorSelected));
            } else if (pager.getProvider() instanceof CustomTabProvider) {
                if (tab instanceof MaterialRippleLayout) {
                    final Component child = ((MaterialRippleLayout) tab).getComponentAt(0);
                    ((CustomTabProvider) pager.getProvider()).onCustomTabViewSelected(child, position, isTabSelected(position));
                } else {
                    ((CustomTabProvider) pager.getProvider()).onCustomTabViewSelected(tab, position, isTabSelected(position));
                }
            }
        }
    }

    private boolean isTabSelected(int position) {
        return position == mSelectedTabPosition;
    }

    private class PagerAdapterObserver extends DataSetSubscriber {

        private boolean attached = false;

        @Override
        public void onChanged() {
            notifyDataSetChanged();
        }

        public void setAttached(boolean attached) {
            this.attached = attached;
        }

        public boolean isAttached() {
            return attached;
        }
    }

    @Override
    public boolean isBoundToWindow() {
        if (pager != null) {
            if (!adapterObserver.isAttached()) {
                pager.getProvider().addDataSubscriber(adapterObserver);
                adapterObserver.setAttached(true);
            } else {
                pager.getProvider().removeDataSubscriber(adapterObserver);
                adapterObserver.setAttached(false);
            }
        }
        return super.isBoundToWindow();
    }

    /**
     * 获取下标颜色
     *
     * @return int
     */
    public int getIndicatorColor() {
        return this.indicatorColor;
    }

    /**
     * 获取下标高度
     *
     * @return int
     */
    public int getIndicatorHeight() {
        return indicatorHeight;
    }

    /**
     * 获取下标未选择颜色
     *
     * @return int
     */
    public int getUnderlineColor() {
        return underlineColor;
    }

    /**
     * 下标高度
     *
     * @return int
     */
    public int getUnderlineHeight() {
        return underlineHeight;
    }

    /**
     * 获取是否为相同宽度tab
     *
     * @return boolean
     */
    public boolean getSameWeightTabs() {
        return sameWeightTabs;
    }

    /**
     * 获取标签字体大小
     *
     * @return int
     */
    public int getTextSize() {
        return tabTextSize;
    }

    /**
     * tab 字体是否大写
     *
     * @return boolean
     */
    public boolean isTextAllCaps() {
        return textAllCaps;
    }

    /**
     * 获取字体颜色
     *
     * @return int
     */
    public int getTextColor() {
        return tabTextColorUnselected;
    }

    /**
     * 获取padding 大小
     *
     * @return int
     */
    public int getTabPaddingLeftRight() {
        return tabPadding;
    }

    /**
     * 设置下标颜色
     *
     * @param indicatorColor i
     */
    public void setIndicatorColor(int indicatorColor) {
        this.indicatorColor = indicatorColor;
        invalidate();
    }

    /**
     * 设置颜色资源id
     *
     * @param resId 颜色
     */
    public void setIndicatorColorResource(int resId) {
        this.indicatorColor = new Color(resId).getValue();
        invalidate();
    }

    /**
     * 设置下标高度
     *
     * @param indicatorLineHeightPx i
     */
    public void setIndicatorHeight(int indicatorLineHeightPx) {
        this.indicatorHeight = indicatorLineHeightPx;
        invalidate();
    }

    /**
     * 设置未选择颜色id
     *
     * @param underlineColor color
     */
    public void setUnderlineColor(int underlineColor) {
        this.underlineColor = underlineColor;
        invalidate();
    }

    /**
     * 设置颜色id
     *
     * @param resId 资源id
     */
    public void setUnderlineColorResource(int resId) {
        this.underlineColor = new Color(resId).getValue();
        invalidate();
    }

    /**
     * 设置下标高度
     *
     * @param underlineHeightPx px
     */
    public void setUnderlineHeight(int underlineHeightPx) {
        this.underlineHeight = underlineHeightPx;
        invalidate();
    }

    /**
     * 设置tab是否相等
     *
     * @param sameWeightTabs sameWeightTabs
     */
    public void setSameWeightTabs(boolean sameWeightTabs) {
        this.sameWeightTabs = sameWeightTabs;
        if (pager != null) {
            postLayout();
        }
    }

    /**
     * 设置tab居中padding
     *
     * @param isPaddingMiddle pad
     */
    public void setPaddingMiddle(boolean isPaddingMiddle) {
        this.isPaddingMiddle = isPaddingMiddle;
        if (isPaddingMiddle) {
            isRefreshed = false;
        }
        if (pager != null) {
            postLayout();
        }
    }

    /**
     * 设置字体是否大写
     *
     * @param textAllCaps text
     */
    public void setAllCaps(boolean textAllCaps) {
        this.textAllCaps = textAllCaps;
    }

    /**
     * 设置字体大小
     *
     * @param textSizePx px
     */
    public void setTextSize(int textSizePx) {
        this.tabTextSize = textSizePx;
        updateTabStyles();
    }

    /**
     * 设置字体未选择颜色
     *
     * @param textColor color
     */
    public void setTextColorUnselected(int textColor) {
        this.tabTextColorUnselected = textColor;
        updateTabStyles();
    }

    /**
     * 设置字体颜色id
     *
     * @param resId id
     */
    public void setTextColorResource(int resId) {
        setTextColorUnselected(new Color(resId).getValue());
    }

    /**
     * 设置字体选择颜色
     *
     * @param textColorSelected color
     */
    public void setTextColorSelected(int textColorSelected) {
        this.tabTextColorSelected = textColorSelected;
        invalidate();
    }

    /**
     * 设置字体选择颜色id
     *
     * @param resId id
     */
    public void setTextColorSelectedResource(int resId) {
        setTextColorSelected(new Color(resId).getValue());
    }

    /**
     * 设置字体样式
     *
     * @param typeface 设置字体样式
     */
    public void setTypefaceSelected(Font typeface) {
        this.tabTypefaceSelected = typeface;
        updateTabStyles();
    }

    /**
     * 设置字体未选择样式
     *
     * @param typeface 设置字体样式
     */
    public void setTypefaceUnselected(Font typeface) {
        this.tabTypefaceUnselected = typeface;
        updateTabStyles();
    }

    /**
     * 设置padding
     *
     * @param paddingPx padding
     */
    public void setTabPaddingLeftRight(int paddingPx) {
        this.tabPadding = paddingPx;
        updateTabStyles();
    }

    /**
     * 设置水波纹扩散颜色
     *
     * @param rippleColor color
     */
    public void setRippleColor(int rippleColor) {
        this.rippleColor = rippleColor;
        notifyDataSetChanged();
    }

    /**
     * 设置tab按下颜色
     *
     * @param rippleHighlightColor color
     */
    public void setRippleHighlightColor(int rippleHighlightColor) {
        this.rippleHighlightColor = rippleHighlightColor;
        notifyDataSetChanged();
    }

    /**
     * 设置水波纹结束的圆角
     *
     * @param rippleOverlay rippleOverlay
     */
    public void setRippleOverlay(boolean rippleOverlay) {
        this.rippleOverlay = rippleOverlay;
        notifyDataSetChanged();
    }

    /**
     * 未用
     *
     * @param rippleDiameterDp rippleDiameterDp
     */
    public void setRippleDiameterDp(float rippleDiameterDp) {
        this.rippleDiameterDp = rippleDiameterDp;
        notifyDataSetChanged();
    }

    /**
     * 设置水波纹动画时间
     *
     * @param rippleDuration rippleDuration
     */
    public void setRippleDuration(int rippleDuration) {
        this.rippleDuration = rippleDuration;
        notifyDataSetChanged();
    }

    /**
     * 设置水波纹透明度
     *
     * @param rippleAlphaFloat float
     */
    public void setRippleAlphaFloat(float rippleAlphaFloat) {
        this.rippleAlphaFloat = rippleAlphaFloat;
        notifyDataSetChanged();
    }

    /**
     * 未用
     *
     * @param rippleDelayClick rippleDelayClick
     */
    public void setRippleDelayClick(boolean rippleDelayClick) {
        this.rippleDelayClick = rippleDelayClick;
        notifyDataSetChanged();
    }

    /**
     * 设置背景色消失时间
     *
     * @param rippleFadeDuration int
     */
    public void setRippleFadeDuration(int rippleFadeDuration) {
        this.rippleFadeDuration = rippleFadeDuration;
        notifyDataSetChanged();
    }

    /**
     * 设置背景色是否消失
     *
     * @param ripplePersistent ripplePersistent
     */
    public void setRipplePersistent(boolean ripplePersistent) {
        this.ripplePersistent = ripplePersistent;
        notifyDataSetChanged();
    }

    /**
     * 原库直接崩溃
     *
     * @param rippleInAdapter rippleInAdapter
     */
    public void setRippleInAdapter(boolean rippleInAdapter) {
        this.rippleInAdapter = rippleInAdapter;
        notifyDataSetChanged();
    }

    /**
     * 设置水波纹结束圆角
     *
     * @param rippleRoundedCornersDp rippleRoundedCornersDp
     */
    public void setRippleRoundedCornersDp(float rippleRoundedCornersDp) {
        this.rippleRoundedCornersDp = rippleRoundedCornersDp;
        notifyDataSetChanged();
    }

}
